/**
 * 文件锁  创建临时文件锁  注意:死锁可能
 * @param name string|number 锁名  格式无检测
 * 		可含目录: opt.temp+'/'+name
 * @param opt object|null 选项参数
 * @param opt.timeout int [锁]超时时间 秒 默认:3
 * @param opt.temp string 创建临时锁文件的目录
 * 		必需:'/'结尾,  默认:取配置$._fsLock
 * @param back function 锁内回调函数
 * @return Promise  back返回数据
 */
$.fsLock = async function(name, opt, back){
	const $P = require('node:path');
	const MKDIR = {mode:'755', recursive:true};
	const P='$.fsLock.', TRY=(Y,N)=>{
		if($.date()*1>Y.T) // 超时:异常
			return N($.err(P+'timeout',null,true));
		const W=$.fsAsync('open',Y.F,'wx').then(fd=>{
			const w=$.fsAsync('close',fd).then(Y);
			w.catch(e=>N($.err(P+'close',e,true)));
		});
		W.catch(()=>setTimeout(TRY,50,Y,N));
	};
	$.fsLock = async function(name, opt, back){
		const T=new Date()*1; opt=$.mix({timeout:3},opt);
		const F = $P.resolve((opt.temp||$._fsLock)+name);
		await $.fsAsync('mkdir', $P.dirname(F), MKDIR)
			.catch(err=>$.err(P+'mkdir',err));
		const [W,Y,N]=$.when();  Y.T=T+opt.timeout*1000;
		Y.F=F;  TRY(Y,N);  await W;  let v;
		try{v=await back();}catch(e){$.err(P+'back',e);}
		return $.fsAsync('unlink',F).then(()=>v)
			.catch(e=>$.err(P+'close',e));
	};
	return $.fsLock(name, opt, back);
};
// [配置]创建临时锁文件的目录
$._fsLock=$._fsLock||$.TEMP+'/.runtime/esFsLock/';
